/*
 * Cubem - Copyright (C) 2008 Ewan Davies
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 *
 */
package cubem;

import javax.microedition.lcdui.*;

/**
 * @author Ewan
 */
public class SessionCanvas extends TimerCanvas {
    /**
     * constructor
     */
    public SessionCanvas() {
        super();
        try {
            setTitle("Cubem Timer");
            /**
             * Prepare fonts
             */
            fnt = Font.getFont(Font.FONT_STATIC_TEXT, Font.STYLE_BOLD, Font.SIZE_LARGE);
            fontHeight = fnt.getHeight() + 2;
            fntLaps = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
            lapFontHeight = fntLaps.getHeight();
            
            /**
             * Prepare everything else
             */
            vOffset = 0;
            status = STATUS_NOT_STARTED;
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Variables
     */
    protected static final int INCREASE_SIZE = 5;
  
    protected Font fnt;
    protected Font fntLaps;
    protected int vOffset;
    protected int fontHeight;
    protected int lapFontHeight;
//    protected long lapTiming[];
//    protected int currentLap;
    public Session session;
    
    /**
     * Paints the canvas
     * @param g the Graphics item for the canvas
     */
    public void paint(Graphics g) {
        /*
         * Prepare current time
         */
        String toPaint = "00:00.00";
        if (status != STATUS_NOT_STARTED) {
            long currTime = 0;
            switch (status) {
                case STATUS_STOPPED:
                    currTime = timeStopped;
                    break;

                case STATUS_RUNNING:
                    currTime = System.currentTimeMillis();
                    break;
            }
            /*
             * Compute time diff
             */
            toPaint = Solve.convertToTimeString(timeStarted, currTime);
        }
            
        /*
         * If running, only update the timing section
         */
        g.setColor(COLOUR_BACKGROUND);
          
        if (status == STATUS_RUNNING) {
            paintCurrentTime(g, toPaint);
        }
        else {
            // clear whole screen
            g.fillRect(0, 0, getWidth(), getHeight());
             /*
             * Draw previous times
             */
            g.setFont(fntLaps);
            g.setColor(COLOUR_FOREGROUND);
            int margin = fntLaps.stringWidth("Avg. ");
            g.drawString("Avg. ", 0, fontHeight + ((vOffset)*lapFontHeight), Graphics.TOP | Graphics.LEFT);
            g.drawString(session.getAverageString(), margin, fontHeight + ((vOffset)*lapFontHeight), Graphics.TOP | Graphics.LEFT);
            for (int i = 0; i < session.getLength(); i++) {
                if (i == session.getBestSolveIndex())
                    g.setColor(COLOUR_BEST_TIME);
                else if (i == session.getWorstSolveIndex())
                    g.setColor(COLOUR_WORST_TIME);
                else
                    g.setColor(COLOUR_FOREGROUND);
                g.drawString(Integer.toString(1+i) + ". ", 0, fontHeight + ((1+i+vOffset)*lapFontHeight), Graphics.TOP | Graphics.LEFT);
                g.drawString(session.getSolve(i).getTimeString(), margin, fontHeight + ((1+i+vOffset)*lapFontHeight), Graphics.TOP | Graphics.LEFT);
            }
            paintCurrentTime(g, toPaint);
        }
        
    }

    /**
     * Paints the given string to the current time region of the screen
     * @param g the Graphics object for the canvas
     * @param toPaint the string to paint
     */
    protected void paintCurrentTime(Graphics g, String toPaint) {
        // clear rectangle for current time
        g.setColor(COLOUR_BACKGROUND);
        g.fillRect(0, 0, getWidth(), fontHeight);
        /*
         * Draw current time
         */
        g.setColor(COLOUR_FOREGROUND);
        g.setFont(fnt);
        g.drawString(toPaint, getWidth() / 2, 0, Graphics.TOP | Graphics.HCENTER);
    }

    public void startTimer() {
        super.startTimer();
        parent.updateSessionCanvasCommands();
    }
    
    /**
     * Stops the timer
     * Override the regular timer stop method as we want to update
     * pllCanvas commands
     */
    public void stopTimer() {
        super.stopTimer();
        parent.updateSessionCanvasCommands();
    }
    
    /**
     * Stores the last achieved time
     */
    public void storeTime(int penalties) {
        if (status == STATUS_STOPPED)
        {
            session.addTime(parent.getScramble(), timeStopped - timeStarted, penalties);
            status = STATUS_NOT_STARTED;
        }
    }
    
    /**
     * Rejects the latest time
     */
    public void rejectTime() {
        if (status == STATUS_STOPPED)
        {
            status = STATUS_NOT_STARTED;
        }
    }

    /**
     * Gets a string representing the last recorded time
     * @return the time as a string
     */
    public String getStoppedTime() {
        return Solve.convertToTimeString(timeStarted, timeStopped);
    }
    
    /**
     * Stores the difference between timeStarted and the given time as a solve
     * @param currTime the time the solve ended
     */
//    protected void storeCurrentLap(long currTime) { 
//        lapTiming[currentLap] = currTime - timeStarted;
//        currentLap++;
//        if (currentLap >= lapTiming.length) {
//            increaseLapsArray();
//        }
//    }
    
    /**
     * Resets the timer
     */
    public void reset() {
        super.reset();
        session = null;
        //lapTiming = null;
        //increaseLapsArray();
        //currentLap = 0;
    }    
    
    /**
     * 
     * @param puzzle
     */
    public void newSession(String puzzle) {
        session = new Session(puzzle);
    }
   
    /**
     * Allocates more space for the times
     */
//    protected void increaseLapsArray() {
//        if (lapTiming == null) {
//            lapTiming = new long[INCREASE_SIZE];
//        } else {
//            long newLaps[] = new long[lapTiming.length + INCREASE_SIZE];
//            System.arraycopy(lapTiming, 0, newLaps, 0, lapTiming.length);
//            lapTiming = newLaps;
//        }
//    }

    /**
     * Called when a key is pressed.
     */
    protected void keyPressed(int keyCode) {
        int action = getGameAction(keyCode);
        switch (action) {
            case FIRE:
                if  (status == STATUS_RUNNING)
                {
                    stopTimer();
                    parent.getStoppedList().setTitle(getStoppedTime());
                    parent.switchDisplayable(null, parent.getStoppedList());
                }
            break;
            case UP:
                if  (status != STATUS_RUNNING) {
                    vOffset--;
                    repaint();
                }
                break;
            case DOWN:
                if  (status != STATUS_RUNNING){
                    vOffset++;
                    repaint();
                }
                break;
        }
        if ((keyCode == KEY_POUND) || (keyCode == KEY_STAR)) {
            if  (status == STATUS_RUNNING)
            {
                stopTimer();
                parent.getStoppedList().setTitle(getStoppedTime());
                parent.switchDisplayable(null, parent.getStoppedList());
            }
        }
    }

    /**
     * Called when a key is released.
     */
    protected void keyReleased(int keyCode) {
       int action = getGameAction(keyCode);
        if (action == FIRE)
            if  (status == STATUS_NOT_STARTED)
                startTimer();
  
        if ((keyCode == KEY_POUND) || (keyCode == KEY_STAR)) {
            if  (status == STATUS_NOT_STARTED)
                startTimer();
        }
    }
}